<template>
  <div class="card-list">
    <div class="card-container" v-for="(item, index) in list">
      <slot :list-item="item" :list-index="index" :list="list"></slot>
    </div>
  </div>
  <div class="page-end page-end-scroll" ref="scrollPager">
    <div v-if="finishedModel">已全部加载</div>
    <div v-else-if="loadingModel">加载中...</div>
    <div v-else @click="getNextList" style="cursor: pointer">滚动到底部加载下一页(点击可加载下一页)</div>
  </div>
</template>

<script setup lang="ts">
import type {WritableComputedRef} from "vue";
import {request} from "@/utils/request";
import ApiResult from "@/api/base/ApiResult";
import {debounce} from "@/utils";

const props = withDefaults(defineProps<{
  url: string;
  loading?: boolean;
  finished?: boolean;
  params?: any;
  data?: any[];
  paginationType?: "scrollPager"
}>(), {
  params: {},
  data: () => [],
  paginationType: "scrollPager",
  loading: undefined,
  finished: undefined,
})

const emits = defineEmits<{
  (e: "update:loading", value: boolean): void
  (e: "update:finished", value: boolean): void
}>()


const loading_private = ref(false);
const finished_private = ref(false);

const loadingModel:WritableComputedRef<boolean> = computed({
  get() {
    if (props.loading === undefined) {
      return loading_private.value
    } else {
      return props.loading;
    }
  },
  set(newVal) {
    if (props.loading === undefined) {
      loading_private.value = newVal;
    } else {
      emits("update:loading", newVal)
    }
  }
})

const finishedModel:WritableComputedRef<boolean> = computed({
  get() {
    if (props.finished === undefined) {
      return finished_private.value
    } else {
      return props.finished;
    }
  },
  set(newVal) {
    if (props.finished === undefined) {
      finished_private.value = newVal;
    } else {
      emits("update:finished", newVal)
    }
  }
})

const pager = reactive({
  currentPage: 0, // 第一页是1， 初始化时会加++ 从1开始
  showCount: 10,
})

const list = ref([]);
const getList = async () => {
  loadingModel.value = true
  const rs:ApiResult<any> = await request(props.url, {
    ...pager,
    ...props.params,
  })
  if (rs.code === 200) {
    list.value = list.value.concat(rs.payload ?? [])
  }
  loadingModel.value = false
  finishedModel.value = (rs.page?.totalPage ?? 0) <= (rs.page?.currentPage ?? 1)
}

const getNextList = () => {
  if (finishedModel.value) {
    return
  }
  ++pager.currentPage
  getList(); 
}

const research = async () => {
  intersectionObserver.unobserve(scrollPager.value)
  pager.currentPage = 0;
  finishedModel.value = false;
  loadingModel.value = true;

  list.value = [];
  // await getList();

  //修复重新查询之后多加载一页的bug
  await getNextList() //修复重新查询之后多加载一页的bug
  intersectionObserver.observe(scrollPager.value)
}

const debouncedResearch = debounce(research, 700, false);

watch(() => props.params, () => {
  debouncedResearch();
}, {
  deep: true
})

const scrollPager = ref();
let intersectionObserver: IntersectionObserver
const initPager = () => {
  intersectionObserver = new IntersectionObserver((entries) => {
    // console.log("observe pageload", entries)
    if (entries[0].intersectionRatio <= 0) {
      // console.log("视野外，不需要再加载")
      return;
    }
    if (loadingModel.value) {
      // console.log("加载中，不需要再加载")
      return
    }
    if (finishedModel.value) {
      // console.log("加载已完成，不需要再加载")
      return
    }

    // console.log("加载！！！")
     getNextList()
  })
  intersectionObserver.observe(scrollPager.value);
}

onMounted(() => {
  initPager()
})

onBeforeUnmount(() => {
  intersectionObserver.disconnect();
})

defineExpose({
  research,
  debouncedResearch,
})
</script>

<style scoped lang="scss">
.card-list {
  min-width: 520px;
  overflow-x: auto;
  display: flex;
  flex-wrap: wrap;

  .card-container {
    width: 265px;
    height: 340px;
    margin-bottom: 20px;
    padding-right: 20px;
    box-sizing: border-box;
    position: relative;
  }

  @media (max-width: 3200px){
    .card-container {
      width: 10%;
    }
  }

  @media (max-width: 2900px){
    .card-container {
      width: 11.11%;
    }
  }

  @media (max-width: 2600px){
    .card-container {
      width: 12.5%;
    }
  }

  @media (max-width: 2300px){
    .card-container {
      width: 14.29%;
    }
  }

  @media (max-width: 2000px) {
    .card-container {
      width: 16.667%;
    }
  }

  @media (max-width: 1700px){
    .card-container {
      width: 20%;
    }
  }

  @media (max-width: 1400px){
    .card-container {
      width: 25%;
    }
  }

  @media (max-width: 1100px){
    .card-container {
      width: 33%;
    }
  }

  @media (max-width: 800px){
    .card-container {
      width: 50%;
    }
  }

  .page-card {
    width: 100%;
    height: 100%;
    box-shadow: 0 0 4px 0 rgba(0,0,0,0.09);
    border-radius: 8px;
    overflow: hidden;

    .img-wrapper {
      width: 100%;
      height: 240px;
      background: rgba(245, 245, 245, 1);
    }

    .info-wrapper {
      display: flex;
      flex-direction: column;
      padding: 10px;
    }

    .single-line {
      overflow: hidden;
      text-overflow: ellipsis;
      word-break: keep-all;
      white-space: nowrap;
    }

    .name {
      color: #333;
      font-size: 16px;
      margin-bottom: 8px;
    }

    .desc {
      color: #666;
      font-size: 14px;
    }

    .desc:not(:last-child) {
      margin-bottom: 6px;
    }
  }

  .card-hover {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    display: block;
    background: rgba(0,0,0, .45);
  }
}

.page-end-scroll {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #999;
  padding: 20px;
}
</style>
